<!DOCTYPE HTML>
<script src="../../resources/testharness.js"></script>
<script src="../../resources/testharnessreport.js"></script>
<script src="./resources/geometry-interfaces-test-helpers.js"></script>
<script>

var matrix2d = [5, 4, 11, 34, 55, 11];
var matrix3d = [5, 11, 55, 77, 44, 33, 55, 75, 88, 99, 12, 43, 65, 36, 85, 25];

test(() => {
  var actualMatrix1 = new DOMMatrix(matrix2d);
  var actualMatrix2 = new DOMMatrix(matrix3d);
  var expectedMatrix = new DOMMatrix();
  actualMatrix1.setMatrixValue("");
  assert_true(actualMatrix1.is2D);
  assert_matrix_almost_equals(actualMatrix1, expectedMatrix);
  actualMatrix2.setMatrixValue("");
  assert_true(actualMatrix2.is2D);
  assert_matrix_almost_equals(actualMatrix2, expectedMatrix);
}, "DOMMatrix setMatrix(EmptyString)");

test(() => {
  var actualMatrix1 = new DOMMatrix(matrix2d);
  var actualMatrix2 = new DOMMatrix(matrix3d);
  var expectedMatrix = new DOMMatrix();
  actualMatrix1.setMatrixValue("none");
  assert_true(actualMatrix1.is2D);
  assert_matrix_almost_equals(actualMatrix1, expectedMatrix);
  actualMatrix2.setMatrixValue("none");
  assert_true(actualMatrix2.is2D);
  assert_matrix_almost_equals(actualMatrix2, expectedMatrix);
}, "DOMMatrix setMatrix('none')");

test(() => {
  var actualMatrix1 = new DOMMatrix(matrix2d);
  var actualMatrix2 = new DOMMatrix(matrix3d);
  var expectedMatrix = new DOMMatrix();
  actualMatrix1.setMatrixValue("matrix(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)");
  assert_true(actualMatrix1.is2D);
  actualMatrix2.setMatrixValue("matrix(1.0, 2.0, 3.0, 4.0, 5.0, 6.0)");
  assert_true(actualMatrix2.is2D);
  expectedMatrix.multiplySelf(new DOMMatrix([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]))
  assert_matrix_almost_equals(actualMatrix1, expectedMatrix);
  assert_matrix_almost_equals(actualMatrix2, expectedMatrix);
}, "DOMMatrix setMatrix('matrix')");

test(() => {
  var actualMatrix1 = new DOMMatrix(matrix2d);
  var actualMatrix2 = new DOMMatrix(matrix3d);
  var expectedMatrix = new DOMMatrix();
  actualMatrix1.setMatrixValue("translate(44px, 55px)");
  assert_true(actualMatrix1.is2D);
  actualMatrix2.setMatrixValue("translate(44px, 55px)");
  assert_true(actualMatrix2.is2D);
  expectedMatrix.translateSelf(44, 55)
  assert_matrix_almost_equals(actualMatrix1, expectedMatrix);
  assert_matrix_almost_equals(actualMatrix2, expectedMatrix);
}, "DOMMatrix setMatrix('translate')");

test(() => {
  var actualMatrix1 = new DOMMatrix(matrix2d);
  var actualMatrix2 = new DOMMatrix(matrix3d);
  var expectedMatrix = new DOMMatrix();
  actualMatrix1.setMatrixValue("translateX(35px)");
  assert_true(actualMatrix1.is2D);
  actualMatrix2.setMatrixValue("translateX(35px)");
  assert_true(actualMatrix2.is2D);
  expectedMatrix.translateSelf(35, 0)
  assert_matrix_almost_equals(actualMatrix1, expectedMatrix);
  assert_matrix_almost_equals(actualMatrix2, expectedMatrix);
}, "DOMMatrix setMatrix('translateX')");

test(() => {
  var actualMatrix1 = new DOMMatrix(matrix2d);
  var actualMatrix2 = new DOMMatrix(matrix3d);
  var expectedMatrix = new DOMMatrix();
  actualMatrix1.setMatrixValue("translateY(77px)");
  assert_true(actualMatrix1.is2D);
  actualMatrix2.setMatrixValue("translateY(77px)");
  assert_true(actualMatrix2.is2D);
  expectedMatrix.translateSelf(0, 77)
  assert_matrix_almost_equals(actualMatrix1, expectedMatrix);
  assert_matrix_almost_equals(actualMatrix2, expectedMatrix);
}, "DOMMatrix setMatrix('translateY')");

test(() => {
  var actualMatrix1 = new DOMMatrix(matrix2d);
  var actualMatrix2 = new DOMMatrix(matrix3d);
  var expectedMatrix = new DOMMatrix();
  actualMatrix1.setMatrixValue("scale(2, 2)");
  assert_true(actualMatrix1.is2D);
  actualMatrix2.setMatrixValue("scale(2, 2)");
  assert_true(actualMatrix2.is2D);
  expectedMatrix.scaleSelf(2, 2);
  assert_matrix_almost_equals(actualMatrix1, expectedMatrix);
  assert_matrix_almost_equals(actualMatrix2, expectedMatrix);
}, "DOMMatrix setMatrix('scale')");

test(() => {
  var actualMatrix1 = new DOMMatrix(matrix2d);
  var actualMatrix2 = new DOMMatrix(matrix3d);
  var expectedMatrix = new DOMMatrix();
  actualMatrix1.setMatrixValue("scaleX(2)");
  assert_true(actualMatrix1.is2D);
  actualMatrix2.setMatrixValue("scaleX(2)");
  assert_true(actualMatrix2.is2D);
  expectedMatrix.scaleSelf(2, 1);
  assert_matrix_almost_equals(actualMatrix1, expectedMatrix);
  assert_matrix_almost_equals(actualMatrix2, expectedMatrix);
}, "DOMMatrix setMatrix('scaleX')");

test(() => {
  var actualMatrix1 = new DOMMatrix(matrix2d);
  var actualMatrix2 = new DOMMatrix(matrix3d);
  var expectedMatrix = new DOMMatrix();
  actualMatrix1.setMatrixValue("scaleY(2)");
  assert_true(actualMatrix1.is2D);
  actualMatrix2.setMatrixValue("scaleY(2)");
  assert_true(actualMatrix2.is2D);
  expectedMatrix.scaleSelf(1, 2);
  assert_matrix_almost_equals(actualMatrix1, expectedMatrix);
  assert_matrix_almost_equals(actualMatrix2, expectedMatrix);
}, "DOMMatrix setMatrix('scaleY')");

test(() => {
  var actualMatrix1 = new DOMMatrix(matrix2d);
  var actualMatrix2 = new DOMMatrix(matrix3d);
  var expectedMatrix = new DOMMatrix();
  actualMatrix1.setMatrixValue("rotate(90deg)");
  assert_true(actualMatrix1.is2D);
  actualMatrix2.setMatrixValue("rotate(90deg)");
  assert_true(actualMatrix2.is2D);
  expectedMatrix.rotateAxisAngleSelf(0, 0, 1, 90);
  assert_matrix_almost_equals(actualMatrix1, expectedMatrix);
  assert_matrix_almost_equals(actualMatrix2, expectedMatrix);
}, "DOMMatrix setMatrix('rotate')");

test(() => {
  var actualMatrix1 = new DOMMatrix(matrix2d);
  var actualMatrix2 = new DOMMatrix(matrix3d);
  var expectedMatrix = new DOMMatrix();
  actualMatrix1.setMatrixValue("skewX(30deg)");
  assert_true(actualMatrix1.is2D);
  actualMatrix2.setMatrixValue("skewX(30deg)");
  assert_true(actualMatrix2.is2D);
  expectedMatrix.skewXSelf(30);
  assert_matrix_almost_equals(actualMatrix1, expectedMatrix);
  assert_matrix_almost_equals(actualMatrix2, expectedMatrix);
}, "DOMMatrix setMatrix('skewX')");

test(() => {
  var actualMatrix1 = new DOMMatrix(matrix2d);
  var actualMatrix2 = new DOMMatrix(matrix3d);
  var expectedMatrix = new DOMMatrix();
  actualMatrix1.setMatrixValue("skewY(40deg)");
  assert_true(actualMatrix1.is2D);
  actualMatrix2.setMatrixValue("skewY(40deg)");
  assert_true(actualMatrix2.is2D);
  expectedMatrix.skewYSelf(40);
  assert_matrix_almost_equals(actualMatrix1, expectedMatrix);
  assert_matrix_almost_equals(actualMatrix2, expectedMatrix);
}, "DOMMatrix setMatrix('skewY')");

test(() => {
  var actualMatrix1 = new DOMMatrix(matrix2d);
  var actualMatrix2 = new DOMMatrix(matrix3d);
  var expectedMatrix = new DOMMatrix();
  actualMatrix1.setMatrixValue("matrix3d(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0)");
  assert_false(actualMatrix1.is2D);
  actualMatrix2.setMatrixValue("matrix3d(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0)");
  assert_false(actualMatrix2.is2D);
  expectedMatrix.multiplySelf(new DOMMatrix([1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0, 11.0, 12.0, 13.0, 14.0, 15.0, 16.0]))
  assert_matrix_almost_equals(actualMatrix1, expectedMatrix);
  assert_matrix_almost_equals(actualMatrix2, expectedMatrix);
}, "DOMMatrix setMatrix(matrix3d)");

test(() => {
  var actualMatrix1 = new DOMMatrix(matrix2d);
  var actualMatrix2 = new DOMMatrix(matrix3d);
  var expectedMatrix = new DOMMatrix();
  actualMatrix1.setMatrixValue("translate3d(10px, 20px, 30px)");
  assert_false(actualMatrix1.is2D);
  actualMatrix2.setMatrixValue("translate3d(10px, 20px, 30px)");
  assert_false(actualMatrix2.is2D);
  expectedMatrix.translateSelf(10, 20, 30)
  assert_matrix_almost_equals(actualMatrix1, expectedMatrix);
  assert_matrix_almost_equals(actualMatrix2, expectedMatrix);
}, "DOMMatrix setMatrix(translate3d)");

test(() => {
  var actualMatrix1 = new DOMMatrix(matrix2d);
  var actualMatrix2 = new DOMMatrix(matrix3d);
  var expectedMatrix = new DOMMatrix();
  actualMatrix1.setMatrixValue("translateZ(88px)");
  assert_false(actualMatrix1.is2D);
  actualMatrix2.setMatrixValue("translateZ(88px)");
  assert_false(actualMatrix2.is2D);
  expectedMatrix.translateSelf(0, 0, 88)
  assert_matrix_almost_equals(actualMatrix1, expectedMatrix);
  assert_matrix_almost_equals(actualMatrix2, expectedMatrix);
}, "DOMMatrix setMatrix('translateY')");

test(() => {
  var actualMatrix1 = new DOMMatrix(matrix2d);
  var actualMatrix2 = new DOMMatrix(matrix3d);
  var expectedMatrix = new DOMMatrix();
  actualMatrix1.setMatrixValue("matrix(1.0, 2.0, 3.0, 4.0, 5.0, 6.0) translate(44px, 55px) skewX(30deg)");
  assert_true(actualMatrix1.is2D);
  actualMatrix2.setMatrixValue("matrix(1.0, 2.0, 3.0, 4.0, 5.0, 6.0) translate(44px, 55px) skewX(30deg)");
  assert_true(actualMatrix2.is2D);
  expectedMatrix.multiplySelf(new DOMMatrix([1.0, 2.0, 3.0, 4.0, 5.0, 6.0]))
  expectedMatrix.translateSelf(44, 55)
  expectedMatrix.skewXSelf(30);
  assert_matrix_almost_equals(actualMatrix1, expectedMatrix);
  assert_matrix_almost_equals(actualMatrix2, expectedMatrix);
}, "DOMMatrix setMatrix(multiple value)");

test(() => {
  var actualMatrix1 = new DOMMatrix(matrix2d);
  var actualMatrix2 = new DOMMatrix(matrix3d);
  var expectedMatrix = new DOMMatrix();
  actualMatrix1.setMatrixValue("translateX(calc(10px + 1px))");
  assert_true(actualMatrix1.is2D);
  actualMatrix2.setMatrixValue("translateX(calc(10px + 1px))");
  assert_true(actualMatrix2.is2D);
  expectedMatrix.translateSelf(11, 0)
  assert_matrix_almost_equals(actualMatrix1, expectedMatrix);
  assert_matrix_almost_equals(actualMatrix2, expectedMatrix);
}, "DOMMatrix setMatrix() with calc function");

test(() => {

  var actualMatrix = new DOMMatrix([1, 2, 3, 4, 5, 6]);
  var expectedMatrix = new DOMMatrix([1, 2, 3, 4, 5, 6]);

  assert_throws_dom("SyntaxError", () => {
    actualMatrix.setMatrixValue("initial");
  }, "CSS-wide keywords are disallowed");

  assert_throws_dom("SyntaxError", () => {
    actualMatrix.setMatrixValue("notExistFunction()");
  }, "can't parse not exist function");

  assert_throws_dom("SyntaxError", () => {
    actualMatrix.setMatrixValue("translateY(50%)");
  }, "using relative units should throw a SyntaxError");

  assert_throws_dom("SyntaxError", () => {
    actualMatrix.setMatrixValue("translateX(1.2em)");
  }, "using relative units should throw a SyntaxError");

  assert_throws_dom("SyntaxError", () => {
    actualMatrix.setMatrixValue("translateX(10ex)");
  }, "using relative units should throw a SyntaxError");

  assert_throws_dom("SyntaxError", () => {
    actualMatrix.setMatrixValue("translateX(10ch)");
  }, "using relative units should throw a SyntaxError");

  assert_throws_dom("SyntaxError", () => {
    actualMatrix.setMatrixValue("translateX(10rem)");
  }, "using relative units should throw a SyntaxError");

  assert_throws_dom("SyntaxError", () => {
    actualMatrix.setMatrixValue("translateX(10vw)");
  }, "using relative units should throw a SyntaxError");

  assert_throws_dom("SyntaxError", () => {
    actualMatrix.setMatrixValue("translateX(10vh)");
  }, "using relative units should throw a SyntaxError");

  assert_throws_dom("SyntaxError", () => {
    actualMatrix.setMatrixValue("translateX(10vmin)");
  }, "using relative units should throw a SyntaxError");

  assert_throws_dom("SyntaxError", () => {
    actualMatrix.setMatrixValue("translateX(10vmax)");
  }, "using relative units should throw a SyntaxError");

  assert_throws_dom("SyntaxError", () => {
    actualMatrix.setMatrixValue("translateX(calc(10px + 1em))");
  }, "using relative units should throw a SyntaxError");

  assert_throws_dom("SyntaxError", () => {
    actualMatrix.setMatrixValue("translateX(calc(10px + 1%))");
  }, "using relative units should throw a SyntaxError");

  assert_throws_dom("SyntaxError", () => {
    actualMatrix.setMatrixValue("translateX(calc(10vw + 1%))");
  }, "using relative units should throw a SyntaxError");

  //actualMatrix should be not changed.
  assert_true(actualMatrix.is2D);
  assert_matrix_almost_equals(actualMatrix, expectedMatrix);

}, "DOMMatrix.setMatrix(): Exception test");

</script>
